% TODO proof-reading
\subsection{Исключения}

Немного переделаем пример \IT{Month} (\myref{Java_2D_array_month}):

\begin{lstlisting}[caption=IncorrectMonthException.java,style=customjava]
public class IncorrectMonthException extends Exception
{
	private int index;

	public IncorrectMonthException(int index)
	{
		this.index = index;
	} 
	public int getIndex()
	{
		return index;
	}
}
\end{lstlisting}

\begin{lstlisting}[caption=Month2.java,style=customjava]
class Month2
{
	public static String[] months = 
	{
		"January", 
		"February", 
		"March", 
		"April",
		"May",
		"June",
		"July",
		"August",
		"September",
		"October",
		"November",
		"December"
	};

	public static String get_month (int i) throws IncorrectMonthException
	{
		if (i<0 || i>11)
			throw new IncorrectMonthException(i);
		return months[i];
	};

	public static void main (String[] args)
	{
		try
		{
			System.out.println(get_month(100));
		}
		catch(IncorrectMonthException e)
		{
			System.out.println("incorrect month index: "+ e.getIndex());
			e.printStackTrace();
		}
	};
}
\end{lstlisting}

Коротко говоря, \TT{IncorrectMonthException.class} имеет только конструктор объекта и один
метод-акцессор.

Класс \TT{IncorrectMonthException} наследуется от \TT{Exception}, \\
так что конструктор \TT{IncorrectMonthException}
в начале вызывает конструктор класса \TT{Exception}, 
затем он перекладывает входящее значение в единственное поле класса \TT{IncorrectMonthException}:

\begin{lstlisting}
  public IncorrectMonthException(int);
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0       
         1: invokespecial #1        // Method java/lang/Exception."<init>":()V
         4: aload_0       
         5: iload_1       
         6: putfield      #2        // Field index:I
         9: return        
\end{lstlisting}

\TT{getIndex()} это просто акцессор.

\IT{Reference} (указатель) на \TT{IncorrectMonthException} передается в нулевом слоте \ac{LVA}
(\IT{this}), \TT{aload\_0} берет его, \TT{getfield} загружает значение из объекта, 
\TT{ireturn} возвращает его.

\begin{lstlisting}
  public int getIndex();
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0       
         1: getfield      #2        // Field index:I
         4: ireturn       
\end{lstlisting}

Посмотрим на \TT{get\_month()} в \TT{Month2.class}:

\begin{lstlisting}[caption=Month2.class]
  public static java.lang.String get_month(int) throws IncorrectMonthException;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=1, args_size=1
         0: iload_0       
         1: iflt          10
         4: iload_0       
         5: bipush        11
         7: if_icmple     19
        10: new           #2        // class IncorrectMonthException
        13: dup           
        14: iload_0       
        15: invokespecial #3        // Method IncorrectMonthException."<init>":(I)V
        18: athrow        
        19: getstatic     #4        // Field months:[Ljava/lang/String;
        22: iload_0       
        23: aaload        
        24: areturn       
\end{lstlisting}

\TT{iflt} по смещению 1 это \IT{if less than} (если меньше, чем).

В случае неправильного индекса, создается новый объект при помощи инструкции \TT{new} 
по смещению 10.

Тип объекта передается как операнд инструкции\\
(и это \TT{IncorrectMonthException}).

Затем вызывается его конструктор, в который передается индекс (через \ac{TOS}) (по смещению 15).

В то время как управление находится на смещении 18, объект уже создан,
теперь инструкция \TT{athrow} берет указатель (\IT{reference})
на только что созданный объект и сигнализирует в \ac{JVM}, чтобы тот нашел подходящий обработчик
исключения.

Инструкция \TT{athrow} не возвращает управление сюда,
так что по смещению 19 здесь совсем другой \gls{basic block},
не имеющий отношения к исключениям, сюда можно попасть со смещения 7.

Как работает обработчик?
Посмотрим на \main в \TT{Month2.class}:

\begin{lstlisting}[caption=Month2.class]
  public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=2, args_size=1
         0: getstatic     #5        // Field java/lang/System.out:Ljava/io/PrintStream;
         3: bipush        100
         5: invokestatic  #6        // Method get_month:(I)Ljava/lang/String;
         8: invokevirtual #7        // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        11: goto          47
        14: astore_1      
        15: getstatic     #5        // Field java/lang/System.out:Ljava/io/PrintStream;
        18: new           #8        // class java/lang/StringBuilder
        21: dup           
        22: invokespecial #9        // Method java/lang/StringBuilder."<init>":()V
        25: ldc           #10       // String incorrect month index: 
        27: invokevirtual #11       // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        30: aload_1       
        31: invokevirtual #12       // Method IncorrectMonthException.getIndex:()I
        34: invokevirtual #13       // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        37: invokevirtual #14       // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        40: invokevirtual #7        // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        43: aload_1       
        44: invokevirtual #15       // Method IncorrectMonthException.printStackTrace:()V
        47: return        
      Exception table:
         from    to  target type
             0    11    14   Class IncorrectMonthException
\end{lstlisting}

Тут есть \TT{Exception table}, которая определяет, что между смещениями 0 и 11 (включительно)
может случится исключение \\
\TT{IncorrectMonthException}, и если это произойдет, то нужно передать
управление на смещение 14.

Действительно, основная программа заканчивается на смещении 11.

По смещению 14 начинается обработчик, и сюда невозможно попасть, 
здесь нет никаких условных/безусловных переходов в эту область.

Но \ac{JVM} передаст сюда управление в случае исключения.

Самая первая \TT{astore\_1} (на 14) берет входящий указатель (\IT{reference}) на объект 
исключения и сохраняет его в слоте 1 \ac{LVA}.

Позже, по смещению 31 будет вызван метод этого объекта \\
(\TT{getIndex()}).

Указатель \IT{reference} на текующий объект исключения передался немного раньше (смещение 30).

Остальной код это просто код для манипуляции со строками: 
в начале значение возвращенное методом \TT{getIndex()}
конвертируется в строку используя метод \TT{toString()}, 
затем эта строка прибавляется к текстовой строке
\q{incorrect month index: } (как мы уже рассматривали ранее),
затем вызываются \TT{println()} и \TT{printStackTrace()}.

После того как \TT{printStackTrace()} заканчивается, исключение уже обработано, мы можем
возвращаться к нормальной работе.

По смещению 47 есть \TT{return}, который заканчивает работу функции \main, 
но там может быть любой другой код, который исполнится, если исключения не произошло.

Вот пример, как IDA показывает интервалы исключений:

\begin{lstlisting}[caption=из какого-то случайного найденного на компьютере автора .class-файла]
    .catch java/io/FileNotFoundException from met001_335 to met001_360\
 using met001_360
    .catch java/io/FileNotFoundException from met001_185 to met001_214\
 using met001_214
    .catch java/io/FileNotFoundException from met001_181 to met001_192\
 using met001_195
    .catch java/io/FileNotFoundException from met001_155 to met001_176\
 using met001_176
    .catch java/io/FileNotFoundException from met001_83 to met001_129 using \
met001_129
    .catch java/io/FileNotFoundException from met001_42 to met001_66 using \
met001_69
    .catch java/io/FileNotFoundException from met001_begin to met001_37\
 using met001_37
\end{lstlisting}

